package cms.utils.myutiil;

import cms.constant.MessageConstant;

import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Scanner;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class FileUtilF {
    private static Scanner sc = new Scanner(System.in);


    /**
     * 给定一个目录 fileDir，以及起始编号 num 和编号位数 length，给目录下所有直接子文件和文件夹编号
     * 编号形式为   num_文件名
     * 比如编号是18， 要求length 3， 原本的一个文件名为  唐诗三百首.txt   =>   018_唐诗三百首.txt
     * 每遍历一个文件，num++，达到编号 fileDir 目录下所有文件的效果
     * @param fileDir 源文件夹（目录）
     * @param num 其实编号
     * @param length 编号长度
     * @author DuanHengFei
     */
    public static void serialFiles(File fileDir, int num, int length){
        if(!fileDir.isDirectory()) {
            return;
        }
        for (File file : fileDir.listFiles()) {
            file.renameTo(new File(fileDir, StrUtilF.getNumberString(num, length) + "_" + file.getName()));
            num++;
        }

    }


    /**
     * 获取用户输入的源文件夹/文件路径
     * 输入的路径可以是文件，也可以是文件夹。但是必须存在
     * 若输入不合法，则会循环提示重新输入
     * @return 返回用户输入的源文件夹/文件路径
     * @author DuanHengFei
     */
    public static File getValidSrcPath(){
        File fi = new File(sc.nextLine());
        while (!fi.exists()) {
            System.out.println("您输入的源目录不存在！！！");
            fi = new File(sc.nextLine());
        }
        System.out.println("√输入的源路径合法√");
        return fi;
    }

    public static File getValidSrcFile(){
        File fi = new File(sc.nextLine());
        while (!fi.exists() || !fi.isFile()) {
            System.out.println("您输入的源目录不存在，或者非文件！！！");
            fi = new File(sc.nextLine());
        }
        System.out.println("√输入的源路径合法√");
        return fi;
    }


    /**
     * 获取用户输入的源文件夹路径（必须是目录/文件夹，不能是文件）
     * 不能为空
     * 若输入不合法，则会循环提示重新输入
     * @return 返回用户输入的路径
     * @author DuanHengFei
     */
    public static File getValidSrcDir() {
        File fi = new File(sc.nextLine());
        while(!fi.exists() || !fi.isDirectory()) {
            System.out.println("输入的路径非法！！！");
            fi = new File(sc.nextLine());
        }
        System.out.println("√输入的源路径合法√");
        return fi;
    }

    /**
     * 获取用户输入的目标文件夹路径(必须存在，必须是文件夹而不是文件)
     * 若输入不合法，则会循环提示重新输入
     * @return 返回用户输入的路径
     * @author DuanHengFei
     */
    public static File getValidDesDir(){
        //必须要是文件夹
        File fi = new File(sc.nextLine());
        while(!fi.isDirectory() || !fi.exists()) {
            System.out.println("输入的目标目录非法！！！");
            fi = new File(sc.nextLine());
        }
        System.out.println("√输入的目标路径合法√");
        return fi;
    }


    /**
     * 如果file是文件，则直接删除
     * 如果file是单级目录，则直接删除
     * 不能递归删除多级目录
     * @param fileDir 需要传入一个File对象
     * @author DuanHengFei
     */
    public static void delSingleFolder(File fileDir) {
        //如果fileDir不存在，则直接return
        if(!fileDir.exists()) {
            return;
        }
        if(fileDir.isFile()) {
            fileDir.delete();
            return;
        }
        for (File file : fileDir.listFiles()) {
            file.delete();
        }
        fileDir.delete();
    }

    /**
     * 删除多级文件夹file
     * 无论是多级还是单级目录，还是文件，皆可删除
     * @param fileDir 需要传入一个File对象
     * @author DuanHengFei
     */
    public static void delMultiFolder(File fileDir) {
        //如果fileDir不存在，则直接return
        if(!fileDir.exists()) {
            return;
        }
        //如果fileDir传进来了一个文件，照样删除之
        if(fileDir.isFile()) {
            fileDir.delete();
        }
        for (File file : fileDir.listFiles()) {
            if(file.isDirectory()) {
                delMultiFolder(file);
            } else if(file.isFile()) {
                file.delete();
            }
        }
        fileDir.delete();
    }


    //给定一个目录
    //如果下边存在一个目录，该目录下都是.avi或者.wmv，则删除该目录
    //遇见avi文件或者.wmv文件，就直接删除

    /**
     * 遍历判断给定文件fi
     * 如果fi是文件，则判断其是不是.avi或者.wmv文件，如果是，则删除
     * 如果fi是目录，则递归遍历它：
     *          1. 若其下存在这样一个目录，该目录下都是.avi活着.wmv文件并且没有文件夹，就删除之
     *          2. 如果存在.avi活着.wmv文件，就删除之
     * @param fi
     * @throws IOException
     * @author DuanHengFei
     */
    public static void delAVIAndWMV(File fi) throws IOException {
        if (!fi.exists()) {
            throw new IOException("源目标路径：[" + fi.getAbsolutePath() + "] 不存在...");
        }


        for (File file : fi.listFiles()) {


            if (file.isFile()) {
                if(file.getName().endsWith(".avi") || file.getName().endsWith(".wmv")) {
                    file.delete();
                }
            }

            if (file.isDirectory()) {
                if(isAllAVIOrWMV(file)) {
                    delSingleFolder(file);
                    return;
                }
                delAVIAndWMV(file);
            }
        }
    }

    /**
     * 判断目录下是否所有文件都是.avi，而且没有文件夹
     * 如果传入的file是一个文件，就判断它是不是.avi活着.wmv，如果是，则返回true；否则返回false
     * 如果传入的file是一个文件夹爱，就判断该file的直接子文件，必须全部都是.avi活着.wmv，并且不能有文件夹，才返回true；否则返回false
     * @param file 需要一个文件对象
     * @return 返回一个布尔类型值
     * @author DuanHengFei
     */
    public static boolean isAllAVIOrWMV(File file) {
        if(file.isFile()) {
            if(file.getName().endsWith(".avi") || file.getName().endsWith(".wmv")) {
                return true;
            }
            return false;
        }

        //到这里，file一定是文件夹
        for (File fi : file.listFiles()) {
            //如果下边有文件夹，就直接返回false
            if(fi.isDirectory()) {
                return false;
            }
            if(!(fi.getName().endsWith(".avi") || file.getName().endsWith(".avi"))) {
                return false;
            }

        }
        return true;
    }

    /**
     * 解压.zip文件，只能解压.zip文件
     * 将sourceFile解压到targetDir
     * @param sourceFile 源文件全文件名
     * @param targetDir
     * @throws RuntimeException
     * @author DuanHengFei
     */
    public static void unZip(File sourceFile, String targetDir) throws IOException {
        long start = System.currentTimeMillis();
        if (!sourceFile.exists()) {
            throw new FileNotFoundException("cannot find the file = " + sourceFile.getPath());
        }
        if(!sourceFile.isFile()) {
            throw new FileNotFoundException("this is not a file = " + sourceFile.getPath());
        }
        ZipFile zipFile = null;
        try{
            zipFile = new ZipFile(sourceFile);
            Enumeration<?> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                if (entry.isDirectory()) {
                    String dirPath = targetDir + "/" + entry.getName();
                    createDirIfNotExist(dirPath);
                } else {
                    File targetFile = new File(targetDir + "/" + entry.getName());
                    createFileIfNotExist(targetFile);
                    InputStream is = null;
                    FileOutputStream fos = null;
                    try {
                        is = zipFile.getInputStream(entry);
                        fos = new FileOutputStream(targetFile);
                        int len;
                        byte[] buf = new byte[1024];
                        while ((len = is.read(buf)) != -1) {
                            fos.write(buf, 0, len);
                        }
                    }finally {
                        try{
                            fos.close();
                        }catch (Exception e){
                            //log.warn("close FileOutputStream exception", e);
                            e.printStackTrace();
                            System.out.println("close FileOutputStream exception");
                        }
                        try{
                            is.close();
                        }catch (Exception e){
                            //log.warn("close InputStream exception", e);
                            System.out.println("close InputStream exception");
                        }
                    }
                }
            }
            //log.info("解压完成，耗时：" + (System.currentTimeMillis() - start) +" ms");
            System.out.println("解压完成，耗时：" + (System.currentTimeMillis() - start) +" ms");
        } finally {
            if(zipFile != null){
                try {
                    zipFile.close();
                } catch (IOException e) {
                    //log.warn("close zipFile exception", e);
                    System.out.println("close zipFile exception");
                }
            }
        }
    }

    /**
     * 如果file不存在，就创建文件夹
     * @param path 传入的path指向的需要是一个文件夹
     * @author DuanHengFei
     */
    public static void createDirIfNotExist(String path){
        File file = new File(path);
        createDirIfNotExist(file);
    }

    /**
     *  如果file不存在，就创建文件夹
     * @param file 传入的file需要是一个文件夹
     * @author engFeiHD
     */
    public static void createDirIfNotExist(File file){
        if(!file.exists()){
            file.mkdirs();
        }
    }

    /**
     * 如果文件不存在，就创建
     * @param file 传入的file需要是一个文件
     * @throws IOException
     * @author DuanHengFei
     */
    public static void createFileIfNotExist(File file) throws IOException {
        createParentDirIfNotExist(file);
        file.createNewFile();
    }

    /**
     * 如果filename的父级目录不存在，就创建其父级目录
     * @param filename 一个File对象的全名（全路径）
     * @author DuanHengFei
     */
    public static void createParentDirIfNotExist(String filename){
        File file = new File(filename);
        createParentDirIfNotExist(file);
    }

    /**
     * 如果file的父级目录不存在，就创建其父级目录
     * @param file  一个File对象
     * @author DuanHengFei
     */
    public static void createParentDirIfNotExist(File file){
        createDirIfNotExist(file.getParentFile());
    }


    /**
     * 递归遍历 resourceFile 目录，对之下的每一个文件都做一定的操作。具体操作由 con 指定
     * @param resourceFile 源目录
     * @param con 指定要对文件做的操作（不能操作文件夹，只能操作 resourceFile 下的所有文件）（参数为一个 File 对象）
     * @throws IOException  如果源目录不存在，则抛出异常
     * @author DuanHengFei
     */
    public static void handleFiles(File resourceFile, Consumer<File> con) throws IOException {
        //默认只操作文件
        handleFiles(resourceFile, con, 1);
    }

    /**
     * 递归遍历 resourceFile 目录，对之下的每一个文件都做一定的操作。具体操作由 con 指定
     * @param resourceFile 源目录
     * @param con 指定要对文件做的操作（不能操作文件夹，只能操作 resourceFile 下的所有文件）（参数为一个 File 对象）
     * @param flag 1 表示只操作文件      2 表示只操作文件夹     3 表示文件夹和文件都操作
     * @throws IOException  如果源目录不存在，则抛出异常
     * @author DuanHengFei
     */
    public static void handleFiles(File resourceFile, Consumer<File> con, int flag) throws IOException {
        if (!resourceFile.exists()) {
            throw new IOException("源目标路径：[" + resourceFile.getAbsolutePath() + "] 不存在...");
        }
        if(resourceFile.isFile()) {
            con.accept(resourceFile);
        }
        // 获取源文件夹下的文件夹或文件
        File[] resourceFiles = resourceFile.listFiles();
        for (File file : resourceFiles) {
            if (file.isFile() && (flag == 1 || flag == 3)) {
                con.accept(file);
            }
            // 复制文件夹
            if (file.isDirectory()) {
                handleFiles(file, con);
                if (flag == 2 || flag == 3) {
                    con.accept(file);
                }
            }
        }
    }

    /**
     * 复制文件夹。将 resourceFile 整个复制到 targetFile 目录下
     * 如果 resourceFile 不存在或者不是目录，则抛出 IOException 异常；
     * 如果 targetFile 不是目录，则抛异常 IOException
     * targetFile 目录不存在，就创建
     * @param resourceFile 源路径
     * @param targetFile   目标路径
     * @author DuanHengFei
     */
    public static void copyFolder(File resourceFile, File targetFile) throws IOException {

        //File resourceFile = new File(resource);
        if (!resourceFile.exists()) {
            throw new IOException("源目标路径：[" + resourceFile.getAbsolutePath() + "] 不存在...");
        }

        if(!targetFile.isDirectory()) {
            throw new IOException("源目标路径：[" + resourceFile.getAbsolutePath() + "] 不是目录...");
        }

        //File targetFile = new File(target);
        if(!targetFile.exists()) {
            targetFile.mkdirs();
        }

        if(resourceFile.isFile()) {
            copyFile(resourceFile, new File(targetFile, resourceFile.getName()));
            return;
        }
        if(!resourceFile.isDirectory()) {
            System.out.println("不是文件，又不是文件夹");
            System.out.println(resourceFile.getAbsolutePath());
            return;
        }
        /*if (!targetFile.exists()) {
            throw new Exception("存放的目标路径：[" + target + "] 不存在...");
        }*/

        // 获取源文件夹下的文件夹或文件
        File[] resourceFiles = resourceFile.listFiles();

        for (File file : resourceFiles) {

            File file1 = new File(targetFile.getAbsolutePath() + File.separator + resourceFile.getName());
            // 复制文件
            if (file.isFile()) {
                //System.out.println("文件" + file.getName());
                // 在 目标文件夹（B） 中 新建 源文件夹（A），然后将文件复制到 A 中
                // 这样 在 B 中 就存在 A
                if (!file1.exists()) {
                    file1.mkdirs();
                }
                File targetFile1 = new File(file1.getAbsolutePath() + File.separator + file.getName());
                copyFile(file, targetFile1);
            }
            // 复制文件夹
            if (file.isDirectory()) {// 复制源文件夹
                //String dir1 = file.getAbsolutePath();
                // 目的文件夹
                //String dir2 = file1.getAbsolutePath();
                copyFolder(file, file1);
            }
        }

    }

    public void copyFolder(String resource, String target) throws Exception {
        this.copyFolder(new File(resource), new File(target));
    }

    /**
     * 复制文件
     * @param resource 源文件全路径
     * @param target 目标文件全路径（可以填目标文件全路径，也可以填目标文件的父目录）
     * @author DuanHengFei
     */
    public static void copyFile(File resource, File target) throws IOException {
        //如果target是一个文件，就直接写入
        //如果target是一个文件夹，就命名复制的目标文件名，等同于源文件名
        if(target.isDirectory()) {
            target = new File(target, resource.getName());
        }

        // 文件输入流并进行缓冲
        FileInputStream inputStream = new FileInputStream(resource);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);

        // 文件输出流并进行缓冲
        FileOutputStream outputStream = new FileOutputStream(target);
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);

        // 缓冲数组
        // 大文件 可将 1024 * 2 改大一些，但是 并不是越大就越快
        byte[] bytes = new byte[1024 * 2];
        int len = 0;
        while ((len = inputStream.read(bytes)) != -1) {
            bufferedOutputStream.write(bytes, 0, len);
        }
        // 刷新输出缓冲流
        bufferedOutputStream.flush();
        //关闭流
        bufferedInputStream.close();
        bufferedOutputStream.close();
        inputStream.close();
        outputStream.close();

    }

    public static void copyFile(String resource, String target) throws Exception {
        copyFile(new File(resource), new File(target));
    }


    public static void createAndInitText(String pathDir) {
        createAndInitText(new File(pathDir));
    }

    /**
     * 在目标文件夹内新建一个文本文件 notes，窗口会等待用户输入。用户可以自由输入信息，这些信息会写入到pathDir直接子文件note.txt
     * 直到用户输入 .end 结束
     * @param pathDir 传入一个文件对象（必须是文件夹，不能是文件）
     * @author DuanHengFei
     */
    public static void createAndInitText(File pathDir) {
        if(!pathDir.exists()) {
            System.out.println(pathDir.mkdir());
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = null;
        try {

            bw = new BufferedWriter(new FileWriter(new File(pathDir, "notes.txt")));
            String line;
            while((line = br.readLine()) != null && !line.equals("end.")) {
                //while((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            //bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //br.close();
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("文本写入OK");
        }


    }

    public static void appendNotes(String srcStr, String desStr) {
        appendNotes(new File(srcStr), new File(desStr));
    }

    /**
     * 从源路径 srcFile 读取文本文件，追加写入目标文件 desFile
     * @param srcFile 源文件（必须是文件）
     * @param desFile 目标文件（必须是文件）
     * @author DuanHengFei
     */
    public static void appendNotes(File srcFile, File desFile) {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader(srcFile);
            fw = new FileWriter(desFile, true);
            fw.write("\r\n");
            char[] chArr = new char[1024];
            int len;
            while((len = fr.read(chArr)) != -1) {
                fw.write(chArr, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("追加文本失败");
        } finally {
            try {
                fr.close();
                fw.close();
            }catch (IOException e) {
                e.printStackTrace();
                System.out.println("关闭流的时候貌似出了问题（追加写入文本）");
            }
        }
    }

    public static void appendAllTxt(String srcStr, String desStr) {
        appendAllTxt(new File(srcStr), new File(desStr));
    }

    /**
     * 找到源目录下所有txt文件，追加写入desFile
     * @param srcDir 源文件目录（必须是目录）
     * @param desFile 目标文件（必须是文件）
     * @author DuanHengFei
     */
    public static void appendAllTxt(File srcDir, File desFile) {
        if(srcDir.isFile()) {
            appendNotes(srcDir, desFile);
            return;
        }
        for (File file : srcDir.listFiles()) {
            if(file.getName().endsWith(".txt")) {
                appendNotes(file, desFile);
                file.delete();
            }
        }
    }


    /**
     * 用于同一个文件夹下有过多的文件情况。
     * 将源目录srcDir下所有文件或文件夹。
     * 每 everyCount 个为一组。每组都在目标目录desDir下新建一个目录，存放该组所有文件或文件夹
     * 新建的目录名字由数字编号，编号数字从 initialIndex 开始
     * 编号长度由参数 length 指定
     * @param srcDir 源目录
     * @param desDir 目标目录
     * @param everyCount 每组的文件个数
     * @param length 编号长度
     * @param initialIndex 起始编号
     * @author DuanHengFei
     */
    public static void groupFile(File srcDir, File desDir, int everyCount, int length, int initialIndex) {
        //如果srcDir或desDir不是文件夹，就直接结束本方法
        if(!srcDir.isDirectory() || !desDir.isDirectory()) {
            return;
        }
        File childDesDir = null;
        int index = initialIndex; //记录下一个要新建的desDir的子目录编号
        int i = 0;  //计数器
        for (File file : srcDir.listFiles()) {
            if(i % everyCount == 0) {

                //新的目录名字
                String strName = StrUtilF.getNumberString(index, length);
                //创建目录
                childDesDir = new File(desDir, strName);
                if(!childDesDir.exists()) {
                    childDesDir.mkdirs();
                }
                index++;
            }
            //将file拷贝到childDesDir目录下
            try {
                copyFolder(file, childDesDir);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("拷贝文件的时候出了问题");
            }

            i++;
        }

    }

    public static void groupFile(File srcDir, File desDir, int everyCount, int length) {
        groupFile(srcDir, desDir, everyCount, length, 1);
    }

    public static void groupFile(String srcDir, String desDir, int everyCount, int length) {
        groupFile(new File(srcDir), new File(desDir), everyCount, length);
    }

    /**
     * 计算目录下所有文件/目录个数
     * @param file 传入一个file对象
     * @return 返回该目录下所有的直接子级文件/目录（file需要是目录）。如果file不存在，则返回-2；file是文件，则返回-1。
     * @author DuanHengFei
     */
    public static int countFiles(File file) {
        if(!file.exists()){
            return -2;
        }
        if(file.isFile()) {
            return -1;
        }
        return file.listFiles().length;
    }
    public static int countFiles(String file) {
        return countFiles(new File(file));
    }

    /**
     * 判断目录 fi 下是否有与字符串名字 strDir 相同的文件夹/文件
     * @param fi File对象，必须是目录。如果是文件或者不存在，就返回-1，表示该对象参数非法
     * @param strDir 要找的文件名字符串（非全路径，仅仅是文件名）
     * @return 返回1表示是，返回0表示否，返回-1表示传入的 fi 非法
     * @author DuanHengFei
     */
    public static int hasSameDirName (File fi, String strDir) {
        if(fi.isFile() || !fi.exists()) {
            //返回-1，说明传入的fi非法
            return -1;
        }
        for (String s : fi.list()) {
            if(s.equals(strDir.trim())) {
                //返回1，有相同名字的文件夹
                return 1;
            }
        }
        //返回0，即没有同名文件夹
        return 0;
    }
    public static int hasSameDirName (String fi, String strDir) {
        return hasSameDirName(new File(fi), strDir);
    }

    /**
     * 获取文件的后缀名
     * @param fi
     * @return
     * @author DuanHengFei
     */
    public static String getExtensionName(File fi) {
        //如果是文件夹，或者fi不存在，就返回null
        if(!fi.exists() || fi.isDirectory()) {
            return null;
        }
        if(fi.isFile()) {
            return fi.getName().substring(fi.getName().lastIndexOf(".") + 1);
        }
        return null;
    }
    public static String getExtensionName(String filename) {
        return filename.substring(filename.lastIndexOf(".") + 1);
    }

    //
    //

    /**
     * 判断一个文件是否是图片文件 对bmp,jpg,png,tif,gif做校验
     * @param fi
     * @return
     * @author DuanHengFei
     */
    public static boolean isImg(File fi) {
        if(fi.isDirectory()) {
            return false;
        }
        String exName = getExtensionName(fi).toLowerCase().trim();
        if(fi.isFile()) {
            if(exName.equals("jpg") || exName.equals("jpeg") || exName.equals("bmp")
                    || exName.equals("png") || exName.equals("tif") || exName.equals("gif")
                    || exName.equals("webp") || exName.equals("jfif")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 方法描述: 判断该文件是否是视频
     *
     * @param fi
     * @Return {@link boolean}
     * @throws
     * @author duanhengfei
     * @date 2021年02月13日 20:13:48
     */
    public static boolean isVideo(File fi) {
        String exNameOriginal = getExtensionName(fi);
        if(exNameOriginal == null || "".equals(exNameOriginal)) {
            return false;
        }
        String exName = exNameOriginal.toLowerCase().trim();
        if(fi.isFile()) {
            if(exName.equals("avi") || exName.equals("mov") || exName.equals("ts")
                    || exName.equals("rmvb") || exName.equals("rm") || exName.equals("flv")
                    || exName.equals("mp4") || exName.equals("3gp") || exName.equals("mpeg") || exName.equals("mpg")
                    || exName.equals("asf") || exName.equals("wmv") || exName.equals("navi")
                    || exName.equals("mkv") || exName.equals("f4v") || exName.equals("swf")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 读取一个文件中的文本内容，需指定编码charset
     * @param fi
     * @return
     * @throws IOException
     * @author DuanHengFei
     */
    public static String readTxtFile(File fi, String charset) throws IOException {
        StringBuilder sb = new StringBuilder();
        InputStreamReader isr = new InputStreamReader(new FileInputStream(fi), charset);
        char[] chs = new char[1024];
        int len;
        while((len = isr.read(chs)) != -1) {
            sb.append(new String(chs, 0, len));
        }
        return sb.toString();
    }

    public static String readTxtFile(File fi) throws IOException {
        return readTxtFile(fi, "UTF-8");
    }

    /**
     * 将特定字符串一次性写入到目标文件
     * @param str
     * @param fi
     * @return
     * @throws IOException
     * @author DuanHengFei
     */
    public static boolean writeTxtFile(String str, File fi, String charset) throws IOException {
        if(!fi.isDirectory()) {
            if(!fi.exists()) {
                fi.createNewFile();
            }
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fi), charset);
            osw.write(str);
            osw.flush();
            osw.close();
            return true;

        } else {
            return false;
        }
    }

    public static boolean writeTxtFile(String str, File fi) throws IOException {
        return writeTxtFile(str, fi, "UTF-8");
    }


    public static String removeExtension(String filename) {
        int lastDotIndex = filename.lastIndexOf(".");
        return filename.substring(0, lastDotIndex);
    }

    /**
     * 方法描述: 读取所有图片的相对路径
     *
     * @param sourceFileDir
     * @Return {@link ArrayList< String>}
     * @throws
     * @author duanhengfei
     * @date 2021年01月29日 16:53:11
     */
    public static List<String> readAllImgRelativePath(File sourceFileDir) throws IOException {
        List<String> list = new ArrayList();
        FileUtilF.handleFiles(sourceFileDir, (file) -> {
            if (FileUtilF.isImg(file)) {
                String prefix = sourceFileDir.getAbsolutePath();
                String absolutePath = file.getAbsolutePath();
                list.add(absolutePath.substring(prefix.length()));
            }
        });
        return list;
    }

    /**
     * 方法描述: 读取所有图片
     *
     * @param sourceFileDir
     * @Return {@link ArrayList< String>}
     * @throws
     * @author duanhengfei
     * @date 2021年01月29日 16:53:11
     */
    public static List<File> readAllImgFile(File sourceFileDir) throws IOException {
        return readAllFileConditional(sourceFileDir, 1);
    }

    /**
     * 方法描述: 读取指定文件List
     *
     * @param sourceFileDir
     * @param flag 1 图片， 2 视频
     * @Return {@link List< File>}
     * @throws
     * @author duanhengfei
     * @date 2021年02月14日 10:34:55
     */
    public static List<File> readAllFileConditional(File sourceFileDir, int flag) throws IOException {
        List<File> list = new ArrayList();
        FileUtilF.handleFiles(sourceFileDir, (file) -> {
            if(flag == 1) {
                if (FileUtilF.isImg(file)) {
                    list.add(file);
                }
            }
            if(flag == 2) {
                if (FileUtilF.isVideo(file)) {
                    list.add(file);
                }
            }
        });
        return list;
    }

    /**
     * 方法描述: 读取当前目录下所有文件，列出来列表，并且写一个txt文件
     *
     * @param
     * @Return
     * @throws
     * @author duanhengfei
     * @date 2021年01月30日 10:16:09
     */
    public static void outLineOneLevelFile() throws IOException {
        System.out.println("请输入源目录：");
        File validSrcDir = FileUtilF.getValidSrcDir();
        outLineOneLevelFile(validSrcDir);
    }

    /**
     * 方法描述: 读取当前目录下所有文件，列出来列表，并且写一个txt文件
     *
     * @param
     * @Return
     * @throws
     * @author duanhengfei
     * @date 2021年01月30日 10:16:09
     */
    public static void outLineOneLevelFile(File validSrcDir) throws IOException {
        File[] listFileArr = validSrcDir.listFiles();
        List<File> fileList = new ArrayList<>();
        List<File> dirList = new ArrayList<>();
        for (int i = 0; i < listFileArr.length; i++) {
            File file = listFileArr[i];
            if(file.isDirectory()) {
                dirList.add(file);
            } else {
                fileList.add(file);
            }
        }
        StringBuilder sb = new StringBuilder();
        for (File dir : dirList) {
            sb.append(dir.getName()).append("\r\n");
        }
        for (File file : fileList) {
            sb.append(file.getName()).append("\r\n");
        }
        FileUtilF.writeTxtFile(sb.toString(), new File(validSrcDir.getParent(), getValidTxtName(validSrcDir)));
    }

    /**
     * 方法描述: 获取有效的txt文件名
     *
     * @param validSrcDir
     * @Return {@link String}
     * @throws
     * @author duanhengfei
     * @date 2021年02月25日 09:11:21
     */
    public static String getValidTxtName(File validSrcDir, String description, String endFix) {
        String validName = validSrcDir.getName() + "_" + description + ".txt";
        int index = 1;
        while (new File(validSrcDir.getParent(), validName).exists()) {
            validName = validSrcDir.getName() + "_" + description + "_" + StrUtilF.getNumberString(index++, 4) + endFix;
        }
        return validName;
    }

    public static String getValidTxtName(File validSrcDir) {
        return getValidTxtName(validSrcDir, "列表", ".txt");
    }

    /**
     * 方法描述: 替换掉文件夹下（所有的文件夹和文件） 所有的：为_；  空格替换为空
     *
     * @param
     * @Return
     * @throws
     * @author duanhengfei
     * @date 2021年01月30日 11:16:48
     */
    public static void replaceAllColonAndSpace(File parentDir) throws IOException {
        FileUtilF.handleFiles(parentDir, file -> {
            String name = file.getName();
            if(name.indexOf(":") != -1) {
                String newName = name.replaceAll(":", "_");
                file.renameTo(new File(file.getParent(), newName));
                System.out.println(file.getAbsolutePath());
            }
            if(name.indexOf("：") != -1) {
                String newName = name.replaceAll("：", "_");
                file.renameTo(new File(file.getParent(), newName));
                System.out.println(file.getAbsolutePath());
            }
        }, 3);
    }


    /**
     * 逐行读取文件，每行一个元素，加入到一个List<String>集合中，返回
     *
     * @param validSrcFile
     * @Return {@link List< String>}
     * @throws
     * @author duanhengfei
     * @date 2021年02月01日 19:55:48
     */
    public static List<String> readTxtFileByLine(File validSrcFile) throws IOException {
        return readTxtFileByLine(validSrcFile, "UTF-8");
    }

    public static List<String> readTxtFileByLine(File validSrcFile, String charsetName) throws IOException {
        List<String> resultStrList = new ArrayList<>();
        String lineTxt = null;
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(validSrcFile), charsetName));
        while ((lineTxt = br.readLine()) != null) {
            lineTxt = lineTxt.trim();
            if(lineTxt != null && lineTxt != "") {
                resultStrList.add(lineTxt);
            }
        }
        br.close();
        return resultStrList;
    }

    /**
     * 逐行写文本文件
     *
     * @param desFile
     * @param lineStrList
     * @Return
     * @throws
     * @author duanhengfei
     * @date 2021年02月01日 20:02:13
     */
    public static void writeTxtFileByLine(File desFile, List<String> lineStrList, String charsetName) throws IOException {
        FileOutputStream fos = new FileOutputStream(desFile);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos, charsetName));
        for (String s : lineStrList) {
            bw.write(s);
            bw.newLine();
        }
        bw.close();
    }

    public static void writeTxtFileByLine(File desFile, List<String> lineStrList) throws IOException {
        writeTxtFileByLine(desFile, lineStrList, "UTF-8");
    }

    /**
     * 方法描述: 递归方式 计算文件的大小
     *
     * @param file
     * @Return {@link long}
     * @throws
     * @author duanhengfei
     * @date 2021年02月23日 16:19:58
     */
    public static long getTotalSizeOfFileOrDir(final File file) {
        if (file.isFile())
            return file.length();
        final File[] children = file.listFiles();
        long total = 0;
        if (children != null)
            for (final File child : children)
                total += getTotalSizeOfFileOrDir(child);
        return total;
    }

    public static void removeSuffix(File validParentDir, String suffix) throws IOException {
        if(!validParentDir.exists()) {
            System.out.println("不存在");
            return;
        }
        String str = suffix.toLowerCase();
        if(validParentDir.isFile()) {
            if(validParentDir.getName().toLowerCase().endsWith(str)) {
                validParentDir.renameTo(new File(validParentDir.getParentFile(), validParentDir.getName().substring(0, validParentDir.getName().length() - suffix.length())));
            }
            System.out.println(MessageConstant.EVERYTHING_IS_OK);
            return;
        }
        //validParentDir是文件夹
        handleFiles(validParentDir, file -> {
            if(file.getName().toLowerCase().endsWith(str)) {
                file.renameTo(new File(file.getParentFile(), file.getName().substring(0, file.getName().length() - suffix.length())));
            }
        }, 1);
        System.out.println(MessageConstant.EVERYTHING_IS_OK);
    }

    /**
     * 获取有效的目标文件夹
     *
     * @param parentDir
     * @Return {@link File}
     * @throws
     * @author duanhengfei
     * @date 2021年04月26日 19:11:55
     */
    public static File getValidTargetDir(File parentDir, String description) {
        int index = 0;
        File targetDir = new File(parentDir.getParentFile(), parentDir.getName() + "_" + description + "_" + StrUtilF.getNumberString(index, 4));
        while (targetDir.exists()) {
            index++;
            targetDir = new File(parentDir, "_" + description + "_" + StrUtilF.getNumberString(index, 4));
        }
        targetDir.mkdirs();
        return targetDir;
    }

    public static File getValidTargetDir(File parentDir) {
        return getValidTargetDir(parentDir, "");
    }

    /**
     * 是否 所有的孩子都是文件
     *
     * @param parentDir
     * @Return {@link boolean}
     * @throws
     * @author duanhengfei
     * @date 2021年04月26日 21:50:53
     */
    public static boolean allChildIsFile(File parentDir) {
        if(parentDir.isFile()) {
            return false;
        }
        for (File file : parentDir.listFiles()) {
            if(!file.isFile()) {
                return false;
            }
        }
        return true;
    }

    public static Scanner getSc() {
        return sc;
    }
}
